package org.jeecg.modules.fund.util;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.fund.entity.FundLibrary;
import org.jeecg.modules.fund.entity.FundValue;
import org.jeecg.modules.fund.mapper.FundLibraryMapper;
import org.jeecg.modules.fund.mapper.FundValueMapper;
import org.jeecg.modules.fund.service.IFundLibraryService;
import org.jeecg.modules.fund.service.IFundValueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Deprecated
@Slf4j
@Component
public class Demo {
    @Autowired
    private IFundValueService fundValueService;
    @Autowired
    private FundValueMapper fundValueMapper;
    @Autowired
    private IFundLibraryService fundLibraryService;
    @Autowired
    private FundLibraryMapper fundLibraryMapper;


    public void updateData() throws InterruptedException {
        log.info("开始测试时间：" + DateUtil.now());
        // 总数据量
        int total = 0;
        // 线程池
        ExecutorService executor = new ThreadPoolExecutor(
                4,
                50,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(20000),
                new ThreadPoolExecutor.CallerRunsPolicy()  // 队列满时由主线程执行
        );
        // 根据规则获取代码
        List<FundLibrary> categoryList = fundLibraryService.list(new QueryWrapper<FundLibrary>()
                .select("RIGHT(code,2) as 'code'")
                .groupBy("RIGHT(code,2)"));
        // 批次数组
        List<List<FundLibrary>> batchList = new ArrayList<>();
        for (FundLibrary category : categoryList){
            // 1.获取每个类别的数据
            List<FundLibrary> fundLibraryList = fundLibraryService.list(new QueryWrapper<FundLibrary>()
                    .ne("type", "货币型")
                    .eq("RIGHT(code,2)", category.getCode()));
            // 2.对每个类别数据再进行数据拆分
            // 加到批次列表
            batchList.add(fundLibraryList);
            total += fundLibraryList.size();
        }
        // 用于收集数据（线程安全列表）
        List<FundValue> valueList = Collections.synchronizedList(new ArrayList<>());
        // 使用CountDownLatch等待所有任务完成
        CountDownLatch latch = new CountDownLatch(total);
        AtomicInteger totalSize = new AtomicInteger();
        AtomicInteger nullDataSize = new AtomicInteger();
        for (List<FundLibrary> data : batchList) {
            for (FundLibrary item : data){
                executor.submit(() -> {
                    try {
                        // 远程调用，并处理数据
                        FundValue fundValue = processSingeData(item);
                        if(fundValue != null){
                            totalSize.addAndGet(1);
                            valueList.add(fundValue);
                        } else {
                            nullDataSize.addAndGet(1);
                        }
                        // 检查是否达到批量大小，达到则更新数据库
                        synchronized (valueList){
                            if(valueList.size() >= 100){
                                // 更新完成
                                batchUpdateList(new ArrayList<>(valueList));
                                // 清空数据
                                valueList.clear();
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        // log.info("进入减少1 =>" + latch.getCount());
                        latch.countDown();
                    }
                });
            }
        }
        // 等待所有任务完成
        latch.await();
        executor.shutdown();
        log.info("更新完毕");
        log.info("总数：" + totalSize);
        log.info("空值：" + nullDataSize);
    }

    public FundValue processSingeData(FundLibrary library){
        // 请求接口获取估值
        JSONObject object = FundDataUtil.getEstimateVal(library.getCode());
        // log.info("拉取数据：" + object.toJSONString());
        // 如果没有估算数据，就跳过、QDII没有估值
        if (object != null && !"QDII".equals(library.getType())) {
            // ******* 构造子表实体 *********
            // 日期，注意存在空的情况
            String date = object.getString("gztime");
            // FundId
            String fundId = library.getId();
            // 子表ID
            String valId = fundValueService.createId(fundId, DateUtil.parseDate(date));
            //
            String tableName = fundValueService.tableName(library.getCode());
            // 查询净值
            FundValue value = fundValueMapper.findById(tableName, valId);
            // 空值或者估值，不更新
            if (date != null && (value == null || value.getIsEstimate() == 1)) {
                // 实体构造
                FundValue valueEntity = new FundValue();
                // 设置主键
                valueEntity.setId(valId);
                // 净值日期
                valueEntity.setValDate(DateUtil.parseDate(date));
                // 所属基金ID
                valueEntity.setFundId(fundId);
                // 单位净值
                valueEntity.setNowVal(object.getBigDecimal("gsz"));
                // 日增长率
                valueEntity.setValRate(object.getBigDecimal("gszzl"));
                // 设置状态为估算状态
                valueEntity.setIsEstimate(1);
                // 设置创建时间
                valueEntity.setCreateTime(new Date());
                // 设置更新时间
                valueEntity.setUpdateTime(new Date());
                return valueEntity;
            }
        }
        return null;
    }

    private void batchUpdateList(List<FundValue> valueList){
        log.info("开始批量更新,"+ valueList.size());
    }
}
